<?php
/**
 * Класс отвечающий за вывод, сжатие, слияние и кэширование css файлов 
 * @author Chahin Evgeniy
 * @version 1.1
 * @package Zen_Library
 *
 */
class Zen_Style
{
    
    /**
     * Возвращает текущий контэйнер для стилей
     * @return array
     */
    static function getContainer(){
        if (Zend_Registry::isRegistered('styles')) {
                $styles = Zend_Registry::get('styles');
        }else 
        $styles=array();
        return $styles;
    }
    
    /**
     * Сохраняет текущие стили
     * @param array $styles
     */
    static function setContainer($styles){
            Zend_Registry::set('styles', $styles);
    }
    
    /**
     * Добавление файла для загрузки
     * @param string $name - относительный путь до css файла
     * @param int $order - порядок загрузки 
     * @param string $library - имя библиотеки (файлы с одинаковым именем библиотеки подгружаються одним файлом)
     */
    static function add ($name,$library=0, $order=0, $ie=false)
    {
        $styles=self::getContainer();
        $name=trim($name);
        if(!isset($styles['files'][$name]))
        {
            while(isset($styles['libs'][$library][$order])){
                $order++;
            }
        $styles['libs'][$library][$order]=array('name'=>$name,'order'=>$order,'lib'=>$library,'ie'=>$ie);
        $styles['files'][$name]=array('name'=>$name,'order'=>$order,'lib'=>$library,'ie'=>$ie);
        }
        self::setContainer($styles);
    }
    /**
     * Удаление файла из списка
     * @param strng $name - относительный путь до css файла
     */
    static function remove ($name)
    {
        $styles=self::getContainer();
        $styles['remove'][$name]='1';
        if(isset($styles['files'][$name]))
        {	
            $file=$styles['files'][$name];
            unset($styles['libs'][$file['lib']][$file['order']]);
            unset($styles['files'][$name]);
        }
        self::setContainer($styles);
    }
    
    /**
     * Сжатие css строки
     * @param string $css - css код
     * @return string
     */
    static function compress ($css)
    {
        $search = array(1 => "/(\/\*|\<\!\-\-)(.*?)(\*\/|\-\-\>)/s" , // Удаление всех комментариев
        2 => "/(\s+)?([,{};:>\+])(\s+)?/s" , // Удаление ненужных пробелов
        3 => "/url\(['\"](.*?)['\"]\)/s" , // Удаление кавычек из урлов
        4 => "/;{2,}/is" , // Remove unecessary semi-colons
        5 => "/\s+/s");// Сжатие нескольких пробелов в один
        $replace = array(1 => ' ' , 2 => '$2' , 3 => 'url($1)' , 4 => ';' , 5 => ' ');
        $css = trim(preg_replace($search, $replace, $css));
        return ($css);
    }
    
    
    /**
     * Замена старых путей в файлах на новые относительно папки кеша
     * @param string $css - css код
     * @param string $path - Относительный путь к новому файлу
     * @return string
     */
    static function parsingUrls ($css, $path)
    {
        $files = array();
        preg_match_all("/url\((.*?)\)/i", $css, $files);
        foreach ($files[1] as $file) {
            if ((! preg_match('/^\/{1}/', $file))&&(! preg_match('/^data/', $file))){
                $css = str_replace('url(' . $file . ')', 'url(' . $path . $file . ')', $css);
            }
        }
        return ($css);
    }
    
    /**
     * Вывод ссылок на css файлы
     * @return string
     */
    static function render ()
    {
       $styles=self::getContainer();
       $res = "";//Возвращаемый результат
       $cnf = Zend_Registry::get('cnf');//Конфиг
       
    	if (! file_exists ( $cnf->cache_dir.'jscss')) {
			mkdir ( $cnf->cache_dir.'jscss', 0777, true );
		}
       
            if (sizeof($styles) > 0) {
                //Сортировка
                foreach($styles['libs'] as $lib=>$value){
                   ksort($styles['libs'][$lib]);
                   }
                ksort($styles['libs']);       
                //Если нужно загружать файлы по отдельности т.е. простой вывод всех файлов
                if ($cnf->styles->implode == false) {
                    foreach ($styles['libs'] as $files) {
                        foreach ($files as $file)
                        {
                        	if(!isset($styles['remove'][$file['name']])){
                            if($file['ie']==true)
                            $res.='<!--[if IE]><link rel="stylesheet" href="' . $file['name'] . '" type="text/css" media="screen, projection" /><![endif]-->'.PHP_EOL;                                        
                            else 
                            $res.='<link rel="stylesheet" href="' . $file['name'] . '" type="text/css" media="screen, projection" />'.PHP_EOL;
                        	}
                        }
                    }
                } else 
                //Если нужно склеить файлы в библиотеки                
                {
                	
                      foreach ($styles['libs'] as $lib=>$files) {
                        $ie=false;  
                        $cache_file_name="";
                        foreach ($files as $key=>$file)
                        {        
                        	//Если файл помечен к удалению
                            if(!isset($styles['remove'][$file['name']])){
	                        	//Если это не внешний ресурс
                            	if(!preg_match('/^http/', $file['name'])){
		                        	$root=preg_replace('/\\/$/','',ROOT_PATH);
		                            $name=preg_replace('/^\\//','',$file['name']);
		                            $real_name = $root .'/'. $name;
		                            
		                            $date = filemtime($real_name);
		                            $cache_file_name .= $file['name'] . $date;
		                            $ie=$file['ie'];
	                            }
	                            	//Если ресурс внешний
	                            else{
	                            	if($file['ie']==true){
	                            		$ie=true;
	                       	 			$res.='<!--[if IE]><link rel="stylesheet" href="' . $file['name'] . '" type="text/css" media="screen, projection" /><![endif]-->'.PHP_EOL;
	                            	}else{
	                            		$ie=false;
	                            	    $res.='<link rel="stylesheet" href="' . $file['name'] . '" type="text/css" media="screen, projection" />'.PHP_EOL;
	                            	}
	                            	unset($files[$key]);
	                            }
                            }else{
                            	unset($files[$key]);
                            }
                        }
                        $cache_file_name =  md5($lib.$cache_file_name);
                        $rel_path = '/site/cache/jscss/' . $cache_file_name . ".css";
                            if (! file_exists($cnf->cache_dir . 'jscss/' . $cache_file_name . ".css")) {
                                $data = " ";
                                if(sizeof($files)>0){
                                	foreach ($files as $file) {
                                    	$root=preg_replace('/\\/$/','',ROOT_PATH);
                                    	$name=preg_replace('/^\\//','',$file['name']);
                                    	$real_name = $root .'/'. $name;
                                    	$content = Zen_Style::compress(file_get_contents($real_name));
                                    	$path = explode('/', $file['name']);
                                    	$c = sizeof($path) - 1;
                                    	$fname = $path[$c];
                                    	$path = str_replace($fname, '', $file['name']);
                                    	$content = Zen_Style::parsingUrls($content, $path);
                                    	$data .= $content;
                                	}
                                file_put_contents($cnf->cache_dir . 'jscss/' . $cache_file_name . ".css", $data);
                                }
                         }
                        if($ie==false)
                        { $res .= '
                        <link rel="stylesheet" href="' . $rel_path . '" type="text/css" media="screen, projection" />';
                        }
                         else{
                         $res .= '
                        <!--[if IE]><link rel="stylesheet" href="' . $rel_path . '" type="text/css" media="screen, projection" /><![endif]-->';
                         }
                    }
                    
                }
                return $res;
                
            }
    }
}